import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
import { Request } from "express";
import { createHash } from "crypto";
import { UserAuthService } from "../services/user-auth.service";

// 与前端 Utils.K 一致
const K = "OQVCB0WVHWB2GPS6";

const WHITE_LIST: Array<{ method?: string; path: RegExp }> = [
  { path: /^\/user-service\/user\/login$/ },
  { path: /^\/user-service\/user\/register$/ },
  { path: /^\/user-service\/user\/resetPwd$/ },
  { path: /^\/user-service\/user\/captcha$/ },
  { path: /^\/user-service\/user\/captchaReg$/ },
  { path: /^\/user-service\/user\/captchaImg/ },
  { path: /^\/user-service\/user\/weixinAuth/ },
  { path: /^\/$/ },
  // 娱乐城测试接口（临时添加到白名单，生产环境应该移除）
  { path: /^\/casino\/rps\/challenges$/ },
  { path: /^\/casino\/rps\/challenge-records$/ },
  { path: /^\/casino\/rps\/response-records$/ },
  { path: /^\/casino\/rps\/win-rankings$/ },
  { path: /^\/casino\/rps\/profit-rankings$/ },
];

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private readonly userAuthService: UserAuthService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const req = context.switchToHttp().getRequest<Request>();
    const path = req.path;
    const method = req.method.toUpperCase();

    if (WHITE_LIST.some((r) => r.path.test(path))) {
      return true;
    }

    // 校验 key 头
    const key = (req.headers["key"] ||
      req.headers["Key"] ||
      req.headers["KEY"]) as string | undefined;
    if (!key || key.length < 6) return false;
    const t = key.substring(0, 6);
    const expect = t + this.md5(t + K).substring(6);
    if (key !== expect) return false;

    // 校验 token 与 userId 头
    const userIdHeader = (req.headers["userid"] ||
      req.headers["userId"] ||
      req.headers["UserId"]) as string | undefined;
    const token = (req.headers["token"] || req.headers["Token"]) as
      | string
      | undefined;
    const userId = userIdHeader ? Number(userIdHeader) : NaN;
    if (!userId || !token) return false;

    // 直接使用UserAuthService验证token
    const ok = await this.userAuthService.validateToken(token);
    return ok;
  }

  private md5(s: string): string {
    return createHash("md5").update(s).digest("hex");
  }
}
